<template>
  <div class="employees-import">
    <el-card v-if="!visibleDetails" shadow="never" style="border: none;">
      <Step
        v-model="selected.value"
        :select-options="fields"
        :is-editing="isEditing"
        @onSetting="setExcelHeaderField"
        @onCancel="handleCancel"
        @onUpload="handleOnUpload"
      />
    </el-card>

    <div v-else>
      <div style="margin-bottom: 20px;">
        <el-button @click="reset">重新上传</el-button>
        <el-button type="primary" @click="handleOpenSetDefPwdDialog">提交</el-button>
      </div>
      <el-table
        v-loading="loading"
        :data="withPagination"
        border
        style="width: 100%"
      >
        <el-table-column
          align="center"
          label="序号"
          width="80"
        >
          <template v-slot="{ row }">
            {{ row.number }}
          </template>
        </el-table-column>

        <el-table-column align="center" prop="state" label="状态" width="100">
          <template v-slot="{ row }">
            <span v-if="row.state === 'ready'">等待上传</span>
            <span v-else-if="row.state === 'success'" class="row--success">上传成功</span>
            <span v-else class="row--fail">上传失败</span>
          </template>
        </el-table-column>

        <el-table-column align="center" prop="error" label="失败理由" width="100">
          <template v-slot="{ row }">
            <span v-if="row.error === null">无</span>
            <template v-else>
              <el-popover trigger="hover" placement="top">
                <p>失败理由: {{ row.error }}</p>

                <div slot="reference" class="name-wrapper">
                  <span class="row--fail">{{ row.error }}</span>
                </div>
              </el-popover>
            </template>
          </template>
        </el-table-column>

        <el-table-column
          v-for="item in tableCfg"
          :key="item.id"
          align="center"
          :prop="item.prop"
          :label="item.label"
          :width="item.type === 'date' ? '200' : '180'"
        >
          <template v-slot="{ row }">

            <ValueWithInput
              v-if="item.type === 'string'"
              v-model="row[item.prop]"
              :is-editing="row.edit"
              size="mini"
            />

            <ValueWithDate
              v-if="item.type === 'date'"
              v-model="row[item.prop]"
              :is-editing="row.edit"
              placeholder="请选择"
              size="mini"
              style="width: 160px;"
            />

            <template v-if="item.type === 'select'">

              <BankSelect
                v-if="item.prop === 'bank_id'"
                v-model="row[item.prop]"
                :is-editing="row.edit"
              />

              <SchoolSelect
                v-else-if="item.prop === 'school_id'"
                v-model="row[item.prop]"
                :is-editing="row.edit"
              />

              <ValueWithSelect
                v-else
                :value="getValue(row[item.prop],'value')"
                placeholder="请选择"
                :is-editing="row.edit"
                :options="selectOptions[item.prop]"
                size="mini"
                @input="setValue(row,item.prop,selectOptions[item.prop],$event)"
              />
            </template>

          </template>
        </el-table-column>
        <el-table-column
          align="center"
          label="操作"
          fixed="right"
          width="150"
        >
          <template v-slot="{ row, $index }">
            <el-button v-if="!row.edit" size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
            <el-button v-else size="mini" @click="handleSave(row)">保存</el-button>
            <el-button size="mini" type="danger" @click="handleDel($index)">删除</el-button>
          </template>

        </el-table-column>
      </el-table>

      <Pagination
        style="background-color:transparent;"
        :total="analyzed.length"
        :limit="page.pageSize"
        @pagination="handlePageChange"
      />
    </div>

    <el-dialog
      :close-on-click-modal="false"
      title="请设置员工默认登录密码"
      width="30%"
      :visible.sync="defaultPasswordDialogVisible"
    >
      <el-form
        ref="form"
        label-width="80px"
        label-position="top"
        :model="dialogForm.form"
        :rules="dialogForm.rule"
      >
        <el-form-item label="默认密码" prop="password">
          <el-input
            v-model="dialogForm.form.password"
            type="password"
            show-password
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button
          :disabled="loadingStatuses.submit"
          @click="closeDefPwdDialog"
        >
          取 消
        </el-button>

        <el-button
          :disabled="loadingStatuses.submit"
          :loading="loadingStatuses.submit"
          type="primary"
          @click="handleConfirm"
        >
          确 定
        </el-button>
      </div>
    </el-dialog>

  </div>
</template>
<script>
import Step from './components/Step/index.vue'
import ValueWithInput from './components/ValueWithInput/WithInput.vue'
import ValueWithDate from './components/ValueWithInput/WithDate.vue'
import ValueWithSelect from './components/ValueWithInput/WithSelect.vue'
import BankSelect from '@/views/personnel-files/components/Selector/bank.vue'
import SchoolSelect from '@/views/personnel-files/components/Selector/school.vue'
import Pagination from '@/components/Pagination/index.vue'

import { setExcelHeader, getExcelHeader, updateExcelHeader } from '@/api/excelHeader'
import { excelAnalysis, batchImport, generateExcel } from '@/api/v2/entry'
import { getEducation, getSchool, getDept, getPosition, getPolitic, getNation, getBank } from '@/api/basic'
import { getFieldsList } from '@/api/customFields'
import { cloneDeep } from 'lodash-es'
import dayjs from 'dayjs'
import { atLeastN, isArray, isObject } from '@/utils/kris_utils'
const isSelectComponent = [
  'education_id',
  'gender',
  // 'nation_id',
  'marital_id',
  'registered_residence',
  'education_nature',
  'school_id',
  'bank_id',
  'politic_id',
  // 'department_id',
  'position_id'
]

export const defaultSelected = [1, 10, 5]

export default {
  name: '',
  components: {
    Step,
    ValueWithInput,
    ValueWithDate,
    ValueWithSelect,
    BankSelect,
    SchoolSelect,
    Pagination
  },
  data() {
    return {
      page: {
        currentPage: 1,
        pageSize: 10
      },
      loadingStatuses: {
        submit: false
      },
      selected: {
        value: [],
        backUp: [],
        id: null
      },
      fields: [],
      isEditing: false,
      analyzed: [],
      tableCfg: [],
      visibleDetails: false,
      loading: false,
      selectOptions: {
        education_id: [],
        gender: [
          { label: '男', value: 1 },
          { label: '女', value: 0 }
        ],
        // nation_id: [],
        marital_id: [
          { value: 1, label: '未婚' },
          { value: 2, label: '已婚' },
          { value: 3, label: '离婚' },
          { value: 4, label: '丧偶' }
        ],
        registered_residence: [
          { value: 0, label: '城市户口' },
          { value: 1, label: '农村户口' }
        ],
        education_nature: [
          { label: '自考', value: 0 },
          { label: '成人教育', value: 1 },
          { label: '统招', value: 2 }
        ],
        school_id: [],
        bank_id: [],
        politic_id: [],
        // department_id: [],
        position_id: []
      },
      defaultPasswordDialogVisible: false,
      dialogForm: {
        form: {
          password: ''
        },
        rule: {
          password: [
            { type: 'string', required: true, message: '请输入员工默认登录密码', trigger: ['blur', 'change'] },
            { type: 'string', min: 3, message: '密码长度至少3个字符', trigger: ['blur', 'change'] }
          ]
        }
      }
    }
  },
  computed: {
    fieldConfig() {
      return this.fields.filter(item => this.selected.value.includes(item.id))
    },
    withPagination() {
      const { currentPage, pageSize } = this.page
      const employees = this.analyzed
      const begin = currentPage * pageSize - pageSize
      return employees.slice(begin, begin + pageSize)
    }
  },
  created() {
    this.init()
  },
  methods: {

    init() {
      Promise.allSettled([
        this.getExcelHeader(),
        this.getFieldsList(),
        this.getEducationOptions(),
        this.getPositionOptions(),
        // this.getDepartmentOptions(),
        this.getPoliticOptions(),
        this.getSchoolOptions(),
        this.getBankOptions()
      ])
    },

    async getExcelHeader() {
      try {
        const res = await getExcelHeader()
        const { header, id } = res.data
        if (header) {
          this.isEditing = true
          const selected = JSON.parse(header)
          const set = new Set([...defaultSelected, ...selected])
          this.selected.value = Array.from(set)
          this.selected.backUp = cloneDeep(this.selected.value)
          this.selected.id = id
        } else {
          this.selected.value = defaultSelected
        }

        console.log('res getExcelHeader--------->', res)
      } catch (error) {
        throw new Error(error)
      }
    },

    async getFieldsList() {
      try {
        const res = await getFieldsList({
          table: JSON.stringify(['user_details', 'user_companys'])
        })
        this.fields = res.data
      } catch (error) {
        throw new Error(error)
      }
    },

    async getEducationOptions() {
      const result = await getEducation()
      if (result.code !== 200 || !Array.isArray(result.data)) { throw new Error('加载学历选项失败') }

      this.selectOptions.education_id = result.data.map(item => {
        return {
          label: item.name,
          value: item.id
        }
      })
    },

    async getPoliticOptions() {
      const result = await getPolitic()
      if (result.code !== 200 || !Array.isArray(result.data)) { throw new Error('加载政治面貌选项失败') }

      this.selectOptions.politic_id = result.data.map(item => {
        return {
          label: item.name,
          value: item.id
        }
      })
    },

    async getSchoolOptions(kw) {
      const result = await getSchool({ search: kw ?? '' })
      if (result.code !== 200 || !Array.isArray(result.data)) { throw new Error('加载学校选项失败') }

      this.selectOptions.school_id = result.data.map(item => {
        return {
          label: item.school_name,
          value: item.id
        }
      })
    },

    async getBankOptions(kw) {
      const result = await getBank({ search: kw ?? '' })
      if (result.code !== 200 || !Array.isArray(result.data)) { throw new Error('加载银行选项失败') }

      this.selectOptions.school_id = result.data.map(item => {
        return {
          label: item.school_name,
          value: item.id
        }
      })
    },

    async getPositionOptions() {
      const result = await getPosition()
      if (result.code !== 200 || !Array.isArray(result.data)) { throw new Error('加载岗位选项失败') }

      this.selectOptions.position_id = result.data.map(position => {
        return {
          label: position.name,
          value: position.id,
          departmentId: position.department_id
        }
      })
      console.log(this.positionOptions)
    },

    async setExcelHeaderField() {
      if (!this.isEditing) await this.setExcelHeaderApi()
      else await this.updateExcelHeaderApi()
    },

    async setExcelHeaderApi() {
      try {
        const params = {
          data: JSON.stringify(this.selected.value)
        }
        const res = await setExcelHeader(params)

        if (res.code === 201) {
          this.$message.success('设置成功！')

          await this.generateExcel(params)

          this.refresh()
        }
      } catch (error) {
        this.$message.error('设置失败！')
      }
    },

    async generateExcel(data) {
      try {
        const res = await generateExcel(data)
        window.open(res.data.path)
      } catch (error) {
        this.$message.error('Excel生成失败！')
      }
    },

    async updateExcelHeaderApi() {
      const params = {
        data: JSON.stringify(this.selected.value)
      }
      try {
        const res = await updateExcelHeader(params, this.selected.id)
        console.log('res --------->', res)
        if (res.code === 201) {
          this.$message.success('修改成功！')

          await this.generateExcel(params)

          this.refresh()
        }
      } catch (error) {
        this.$message.error('修改失败！')
      }
    },

    refresh() {
      this.selected = this.$options.data().selected
      this.getExcelHeader()
    },

    handleCancel() {
      this.selected.value = this.selected.backUp
    },

    async handleOnUpload(e) {
      try {
        console.log('e --------->', e)
        if (!(e.file instanceof File)) return

        const formData = new FormData()
        formData.append('excel_file', e.file)
        const res = await excelAnalysis(formData)
        if (res.code !== 200 || !Array.isArray(res.data)) {
          throw new Error(res.message ?? '解析Excel文件解析失败')
        }
        console.log('res --------->', res)
        this.analyzed = this.employeesFormatter(res.data)
        this.visibleDetails = true
      } catch (error) {
        console.log('error --------->', error)
        const errMsg = error?.response?.data?.message ??
          '解析Excel文件解析失败'
        this.$message.error(errMsg)
      }
    },

    dateFormatter(date, format = 'YYYY-MM-DD') {
      const d = dayjs(date).format(format)
      return d === 'Invalid Date' ? null : d
    },

    initValue(label, options) {
      if (!label) return null
      return options.find(item => item.label === label)
    },

    getValue(obj, key) {
      // console.log(obj[key],'obj');
      if (!isObject(obj)) return null
      return obj[key] ?? null
    },

    setValue(obj, key, options, value) {
      if (!atLeastN(options, 1)) return
      const option = options.find(item => item.value === value)
      obj[key] = option
    },

    employeesFormatter(data) {
      const { fields, tableCfg } = this.fieldsFormatted(this.fields)
      const fieldConfig = fields
      const f = []
      data.forEach(item => {
        const data = {}
        Object.keys(item).forEach(col => {
          const cfg = fieldConfig[col]
          if (cfg) {
            data[cfg.field] = item[col]

            // if (cfg.type === 'date') data[cfg.field] = item[col]

            if (cfg.type === 'select') data[cfg.field] = this.initValue(item[col], this.selectOptions[cfg.field])
          }
        })
        data['edit'] = false
        data['number'] = item['序号'] / 1
        data['state'] = 'ready'
        data['error'] = null
        f.push(data)
      })
      this.tableCfg = tableCfg
      return f
    },

    fieldsFormatted(data) {
      const fields = {}
      data = data.filter(item => this.selected.value.includes(item.id))

      const tableCfg = data.map(field => {
        return {
          id: field.id,
          type: isSelectComponent.includes(field.field) ? 'select' : field.type,
          // type: field.type,
          prop: field.field,
          label: field.name
        }
      })

      for (const field of data) {
        const value = {
          id: field.id,
          type: isSelectComponent.includes(field.field) ? 'select' : field.type,
          field: field.field
        }
        fields[field.name] = value
      }
      return {
        fields,
        tableCfg
      }
    },

    handleSave(row) {
      this.loading = true
      setTimeout(() => {
        this.$set(row, 'edit', false)
        this.loading = false
      }, 400)
    },

    handleEdit(row) {
      this.loading = true
      setTimeout(() => {
        this.$set(row, 'edit', true)
        this.loading = false
      }, 400)
    },

    handleDel(index) {
      const { currentPage, pageSize } = this.page
      const offset = (currentPage * pageSize) - pageSize
      this.analyzed.splice(offset + index, 1)
    },

    reset() {
      this.analyzed = this.$options.data().analyzed
      this.tableCfg = this.$options.data().tableCfg
      this.visibleDetails = false
    },

    handlePageChange(e) {
      this.page.currentPage = e.page
      this.page.pageSize = e.limit
    },

    handleOpenSetDefPwdDialog() {
      this.defaultPasswordDialogVisible = true
    },

    closeDefPwdDialog() {
      this.defaultPasswordDialogVisible = false
    },

    handleFailItem(failItems, fileReason) {
      if (!isArray(failItems)) { return }
      const len = this.analyzed.length
      for (let i = 0; i < len; i++) {
        const num = this.analyzed[i].number
        if (failItems.includes(num)) {
          this.$set(this.analyzed[i], 'state', 'fail')
          this.$set(this.analyzed[i], 'error', fileReason)
        } else {
          this.$set(this.analyzed[i], 'state', 'success')
          this.$set(this.analyzed[i], 'error', null)
        }
      }
    },

    async handleConfirm() {
      try {
        const flag = await this.validate()
        if (!flag) return

        const data = this.buildParams()
        console.log('data --------->', data)

        if (data.length <= 0) {
          this.$message.warning('没有任何数据可添加！')
          return
        }

        const json = JSON.stringify(data)
        this.loadingStatuses.submit = true
        const params = {
          data: json,
          password: this.dialogForm.form.password
        }
        const result = await batchImport(params)
        this.handleFailItem(result.data, result.message)
        this.loadingStatuses.submit = false
        this.defaultPasswordDialogVisible = false
        this.resetForm()
        if (JSON.stringify(result.data) === '{}' && result.code === 200) {
          this.$message.success(result.message ?? '创建成功')
          this.reset()
        }
      } catch (error) {
        this.loadingStatuses.submit = false
        const errMsg = error?.response?.data?.message ??
          error?.message ??
          '创建失败'
        this.$message.error(errMsg)
      }
    },

    resetForm() {
      this.$refs?.form?.resetFields?.()
    },

    buildParams() {
      const data = cloneDeep(this.analyzed)
      return data.map(item => {
        delete item['edit']
        delete item['state']
        delete item['error']
        Object.keys(item).forEach(key => {
          const d = item[key]
          if (isObject(d)) item[key] = d.label
        })
        return {
          ...item
        }
      })
    },

    validate() {
      return new Promise((resolve) => {
        this.$refs?.form?.validate(flag => {
          resolve(flag)
        })
      })
    }

  }
}
</script>
<style lang="scss" scoped>
.employees-import {
  padding: 20px;
  .row--success {
    color: #52c41a;
  }
  .row--fail {
    color: #f5222d;
  }
}
</style>
